#pragma once

namespace mmath
{
	struct FrustumPersp;
}

namespace mgfx
{
	struct RenderingData;
	struct RenderingSettings;
	class Mesh;
	class CSM;
	class SSAO;

	typedef int ShaderID;
	typedef int TextureID;

	class DeferredPipeline
	{
	public:
		DeferredPipeline();
		~DeferredPipeline();
		static DeferredPipeline & get();
		void render(const RenderingData & data, const RenderingSettings & settings);

	private:
		void initEffects();
		void initLightGeometry();
		void createDeferredRTs();

		void geometryStage(const RenderingData & data, const RenderingSettings & settings);
		void bricksGeometryStage(const RenderingData & data);

		void lightingStage(const RenderingData & data, const RenderingSettings & settings);

		void renderTransparent(const RenderingData & data, const RenderingSettings & settings);

		void renderDirectionalLightsCSM(const RenderingData & data, const RenderingSettings & settings);
		void renderDirectionalLights(const RenderingData & data);
		void renderPointLights(const RenderingData & data);
		void renderSpotShadowMaps(const RenderingData & data);
		void renderSpotLights(const RenderingData & data);

		void showBoundingSpheres(const RenderingData & data);
		void showGBuffer(const RenderingData & data);

		ShaderID mShaderDirLight;
		ShaderID mShaderPointLight;
		ShaderID mShaderSpotLight;
		ShaderID mShaderShadowedSpotLight;
		ShaderID mShaderCSM;
		ShaderID mShaderWireframe;
		ShaderID mShaderDrawGBuffer;
		ShaderID mShaderGeometryStage;
		ShaderID mShaderShadowMap;
		ShaderID mShaderDeferredFinal;

		CSM * mCSM;
		SSAO * mSSAO;

		TextureID mRtDepth;
		TextureID mRtNormal;
		TextureID mRtDiffuse_SpecI;
		TextureID mRtSpecP;
		TextureID mRtLighting;
		TextureID mRtTmp;

		// light geometries
		Mesh * mSphereMesh;
		Mesh * mConeMesh;

		bool mMSAAEnabled;
		uint mMSAASamples;
	};
}